import _ from "lodash";
import md5 from "md5";
import moment from "moment";
import {sha256} from "js-sha256";
import { encode, decode } from 'js-base64';
import {MOUDLE_MAP} from "@constants"
import service from "@service";


export const firstToUpper = (str) => {
    return str.trim().replace(str[0], str[0].toUpperCase());
}
export const uuidv4 = () => {
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
		var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
		return v.toString(16);
	});
}

export const getDataMapFromNodes = (nodes, {idName = 'id', childrenName = "children"} = {}) => {
    let outPut = {};
    const getMapByList = (list, dataMap={}) => {
        if(!list || !list.length) {
            return dataMap;
        }
        list.forEach(v => {
            let children = v[childrenName];
            dataMap[v[idName]] = v;
            if(children) {
                dataMap = getMapByList(children, dataMap);
            }
        })
        return dataMap;
    }
    outPut = getMapByList(nodes, outPut);
    return outPut;
}
// 平铺的node组成tree
export const flatNodesToNodes = (list, config = {}) => {
    let {
        idName = "id",
        childrenName = "children",
        parentName = "parent",
    } = config;

    let parentIdMap = {};
    let idMap = {};
    list.forEach(item => {
        let parentId = item[parentName];
        idMap[item[idName]] = item;
        if (parentId) {
            if (!parentIdMap[parentId]) {
                parentIdMap[parentId] = [item];
            } else {
                parentIdMap[parentId].push(item);
            }
        }
    })
    const getChildrenFromMap = (parentId) => {
        if (!parentId) {
            return null;
        }
        if (!parentIdMap[parentId]) {
            return null;
        }
        return parentIdMap[parentId].map(v => {
            return {
                ...v,
                [childrenName]: getChildrenFromMap(v[idName])
            }
        })
    }
    let out = [];

    list.forEach(item => {
        let parentId = item[parentName];
        if (!idMap[parentId]) {
            out.push({
                ...item,
                [childrenName]: getChildrenFromMap(item[idName])
            })
        }
    })
    return out;
}

// 根据子节点id查找path
export const getPathByLeafId = (id, treeMap, {
    idName = "id",
    parentName = "parent"
} = {}) => {
    let out = [];
    if (!id || !treeMap) {
        return out;
    }

    const unshiftCurrentNode = (id, treeMap) => {
        if (!id) {
            return;
        }
        if (!treeMap[id]) {
            return;
        }

        out.unshift(treeMap[id]);
        unshiftCurrentNode(treeMap[id][parentName], treeMap);
    }

    unshiftCurrentNode(id, treeMap);
    return out;
}

// 从nodes中取path
export const getPathByTreeId = (id, options, configs={}) => {
    if(!options) return;
    let {idName = 'id', children = 'children'} = configs;

    let targetPath = [];
    const getPath = (list = [],  path = [], index = 0) => {
        if(!list || !list.length) return;
        list.forEach(item => {

            path = path.slice(0, index);
            path[index] = item;

            let flag = item[idName] === id;

            if(flag) {
                path[index] = item;
                targetPath = [...path];
            }else if(item[children]&&item[children].length) {
                getPath(item[children], path, index+1 );
            }
        })
    }
    getPath(options);
    return targetPath;
}

export const getSign = (params, appendKey = true) => {
    let strArr = Object.keys(params).filter(k => {
        return (params[k] || params[k] === 0);
    });

    var sotArr = Array.prototype.sort.call(strArr, function (a, b) {
        for (var i = 0; i < a.length; i++) {
            if (a.charCodeAt(i) == b.charCodeAt(i)) continue;
            return a.charCodeAt(i) - b.charCodeAt(i);
        }
    });

    let sign = sotArr.map(k => {
        return `${k}=${params[k]}`
    }).join('&')
    if(appendKey) {
        sign = sign + `&key=${VUE_API_KEY}`
    }
    return md5(sign).toLocaleUpperCase();
}
export const getShaSign = (params, appendKey = true) => {
    let strArr = Object.keys(params).filter(k => {
        return (params[k] || params[k] === 0);
    });

    var sotArr = Array.prototype.sort.call(strArr, function (a, b) {
        for (var i = 0; i < a.length; i++) {
            if (a.charCodeAt(i) == b.charCodeAt(i)) continue;
            return a.charCodeAt(i) - b.charCodeAt(i);
        }
    });
    
    let sign = sotArr.map(k => {
        return `${k}=${params[k]}`
    }).join('&')

    if(appendKey) {
        sign = sign + `&key=${VUE_API_KEY}`
    }
    
    let shaSign = sha256(sign).toLocaleUpperCase();
    let baseSign = encode(shaSign);

    return baseSign;
}

export const getMenuByRoute = (route, menuList) => {
    let routeName = route.name;
    let targetPath = [];
    menuList = menuList || [];

    const getMenu = (list = [],  cb, path = [], index = 0) => {
        if(!cb) return;
        if(!list || !list.length) return;
        list.forEach(item => {

            path = path.slice(0, index);
            path[index] = item;

            if(item.children&&item.children.length) {

                getMenu(item.children,cb, path, index+1 );
            }else {
                let flag = cb(item);

                if(flag) {
                    path[index] = item;
                    targetPath.push([...path]);
                }
            }
        })
    }

    if(routeName === 'iframe') {
        let searchStr = route.fullPath.match(/(?<=iframe\?)[\w|\W]+/)[0];
        const urlSP = new URLSearchParams(searchStr)

        
        let moduleName = urlSP.get('moduleName');
        let isCmsUrl = moduleName === MOUDLE_MAP.cms;
        let curPath = urlSP.get('path');
        getMenu(menuList, (item) => {
            let path = item.path;
            return path === curPath;
        })

    }else {
        getMenu(menuList, (item) => {
            // let itemRouteName = ((item.description||'').match(/(?<=frontName=)\w+(?=%>)/) || [])[0];
            let itemRouteName = item.frontName;
            return itemRouteName === routeName;
        })
    }
    return targetPath;
}
export const hasOwnProperty = (obj, name) => {
    return Object.prototype.hasOwnProperty.call(obj, name)
}

/** 文件流数据下载
 * @param {Blob} data 文件流
 * @param {String} fileName 文件名
 * @param {String} suffix 文件后缀
 * @return {*}
 */
export const createBlobFileDown = ({data,fileName=moment(new Date()).format("YYYYMMDDHHmmss"), suffix='.xlsx'}) => {
	if (!data) return
	const downloadElement = document.createElement("a");
	const href = window.URL.createObjectURL(data);
	downloadElement.href = href;
	downloadElement.download = fileName + suffix
	document.body.appendChild(downloadElement);
	downloadElement.click(); //点击下载
	document.body.removeChild(downloadElement); //下载完成移除元素
	window.URL.revokeObjectURL(href); //释放掉blob对象
}

export const filterNull = (data) => {
	if(data.constructor !== Object) return data
	const tempData = {}
	for (const [key, value] of Object.entries(data)) {
		tempData[key] = value === null ? '' : value
	}
	return tempData
}

/**找到数组匹配的item项
 * @param {array} arr
 * @param {string} value 匹配项值
 * @param {string} get 获取属性
 * @param {string} key 匹配项属性
 * @return {*}
 */
 export const findItem = (arr, value, get="label",key='value') => {
	const item = arr.find(item => item[key] === value) || {}
	return item[get] || ''
}
/** 数据转换为option格式
 * @param {array} arr
 * @param {string} label
 * @param {string} value
 * @return {array}
 */
 export const convertOption = (arr, label, value) => {
	if(Array.isArray(arr) && !arr.length) return []
	const options = arr.map(item => {
		return {
			value: item[value],
			label: item[label],
			...item
		}
	})
	return options
}
/** 对象值转为字符串形式
 * @param {*} obj
 * @return {*}
 */
export const valToString = (obj) => {
	if(!(Object.prototype.toString.call(obj) === '[object Object]')) return obj
	const tempObj = {}
	for(const [key,val] of Object.entries(obj)){
		tempObj[key] = val === null ? '' : String(val)
	}
	return tempObj
}
/** 树型转数组
 * @param {Array} data
 * @return {Array}
 */
export const treeToArray = (data) => {
	if(!Array.isArray(data)) return data
	let arr = []
	data.forEach(item => {
		const {children, ...remain} = item
		arr.push(remain)
		if(item.children && item.children.length) {
			arr.push(...treeToArray(item.children))
		}
	})
	return arr
}

/** 数组转树型
 * @param {Array} arr
 * @param {String} pid 一级父节点值
 * @param {String} pidName 父节点属性名
 * @param {String} idName 节点id属性名
 * @return {Array}
 */
export const ArrayToTree = (arr, {pid='',pidName="parentId", idName="id"}={}) => {
	const tree = []
	const pidFlag = Array.isArray(pid)
	arr.forEach(item => {
		const equal = pidFlag ? pid.includes(item[pidName]) : item[pidName] === pid
		if(equal) {
			const tempArr = arr.filter(iten => {
				const different = pidFlag ? !pid.includes(iten[pidName]) : iten[pidName] !== pid
				return different
			})
			const children = ArrayToTree(tempArr, {pid: item[idName],pidName,idName})
			if(children && children.length) {
				tree.push({...item,children})
			}else {
				tree.push(item)
			}
		}
	})
	return tree
}
/** 毫秒转换为分秒
 * @param {String} msec
 * @return {*}
 */
export const toMinuteSecond = (msec) => {
	const minute = parseInt(Number(msec) / 60)
	return `${!minute ? '' : minute + '分'}${Number(msec) % 60}秒`
}

/**	数组的所有项添加唯一的key
 * @param {Array} arr
 * @param {String} keyName
 * @return {*}
 */
export const onlyKey = (arr, keyName = 'id') => {
	const keys = arr.filter(v => {
		return v?.[keyName]
	})
	keys.sort()
	return arr.map(v => {
		if (!v[keyName]) {
			return {
				...v,
				[keyName]: keys.length ? String(Number(keys.at(-1)[keyName]) + 1) : '1'
			}
		}
		return v
	})
}
/** 清空树节点的空children
 * @param {Array} arr
 * @return {*}
 */
export const clearSpaceChildren = (arr) => {
	arr.forEach(v => {
		if (v?.children.length > 0) {
			clearSpaceChildren(v?.children)
		} else {
			delete v.children
		}
	})
	return arr
}

/**
 * @description: 找到数组中对应的key值项的index
 * @param {array} arr
 * @param {string} itemKey
 * @param {string} key
 * @return {*}
 */
 export const findIndex = (arr, itemKey, key) => {
    return arr.findIndex((item) => {
        return item[itemKey] === key
    })
}
/**数组对象转换为map对象
 * @param {array} arr
 * @param {string} value
 * @param {string} label
 * @return {*}
 */
export const arrayToMap = (arr, value='value', label='label') => {
    const tempArr = []
    arr.forEach(item => {
        tempArr.push([item[value], item[label]])
    })
    return new Map(tempArr)
}
/**清除空格包括中间的
 * @param {string} str
 * @return {*}
 */
export const clearAllSpace = (str) => {
    return str.replace(/\s*/g,"")
}
/** 下载本地文件（模板）方法
 * @param {string} name 文件名
 * @param {*} url 文件路径
 * @return {*}
 */
export const downloadLocalFile = ({ name, url } = {}) => {
    if (!url) {
        return;
    }
    name = name || url.substring(url.lastIndexOf("/") + 1);
    let tagA = document.createElement("a");
    tagA.setAttribute("download", name);
    tagA.setAttribute("href", url);
    document.body.appendChild(tagA);
    tagA.click();
    document.body.removeChild(tagA);
}

/**
 * 白名单模版下载
 * @param {*} param0
 */
export const exportWhiteList = async ({ params, serviceName, type = 'post' } = {}) => {
    let result = await service(serviceName, {
        [type === 'post' ? "data": "params"]: params,
        timeout: 60000,
    });
    let data = result;
    if (data) {
        var blob = new Blob([data]);
        var downloadElement = document.createElement("a");
        var href = window.URL.createObjectURL(blob);
        downloadElement.href = href;
        downloadElement.download =
            "白名单配置模版.xlsx";
        document.body.appendChild(downloadElement);
        downloadElement.click(); //点击下载
        document.body.removeChild(downloadElement); //下载完成移除元素
        window.URL.revokeObjectURL(href); //释放掉blob对象
    }
};
